/**
 * 
 * 上海金扳手信息科技股份有限公司
 * Copyright (c) 1991-2018 Jinbanshou,Inc.All Rights Reserved.
 */
package com.frames.newtable;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.frames.table.T2BDao;
import com.frames.table.T2BVO;
import com.utils.bean.BeanUtil;
import com.utils.validate.Detect;

/**
    * @ClassName: PojoFromTable
    * @Description: 创建单表业务，自动生成表的实体类、增删改查接口和实现mappper
    * @author likai
    * @date 2017年4月9日
    *
    */
public class TablePojoUtil{
	public static Logger log = LoggerFactory.getLogger(TablePojoUtil.class);
	
	private T2BDao t2bDao;
	private TableConfig tableConfig;
	private static TablePojoUtil tableMapperUtil;
	@SuppressWarnings("resource")
	private TablePojoUtil(TableConfig config,String springPath) {
		super();
		ApplicationContext ctx = new ClassPathXmlApplicationContext(springPath);  
		t2bDao= (T2BDao)ctx.getBean("t2BDao");  
		this.tableConfig=config;
	}
	
	public static TablePojoUtil init(TableConfig config,String springPath) {
		if (tableMapperUtil==null) {
			return new TablePojoUtil(config,springPath);
		}
		return tableMapperUtil;
	}
	/*  
	    * @Description:生成pojo
	    * 
	    */
	public  void convertTableToPojoAndMapper() throws Exception {
		T2BVO vo = new T2BVO();
		vo.setPrefix(tableConfig.tablePrefix());//tablePrefix为要刷选出的表的前缀,""为全部表
		vo.setDbname(tableConfig.dbName());
		List<T2BVO> tables = t2bDao.listTables(vo);
		log.info("---------创建开始-----------");
		for (T2BVO t2b : tables) {
			String table=t2b.getTableName();
			String tableComment=t2b.getTableComment();
			vo.setTableName(table);
			List<T2BVO> cols = t2bDao.listTableCols(vo);
			String className="";
			String prefix=tableConfig.tablePrefix();
			if (tableConfig.reomvePrefix()) {	
				if (Detect.notEmpty(prefix)) {
					//去除指定前缀					
				}else {
					//去除全部前缀
					prefix=table.substring(0,table.indexOf("_")+1);
				}
				className = table.replaceFirst(prefix, "");
				
			}else {
				className=table;
			}

			className = BeanUtil.columnToField2(className);
			//生成table对应的实体类pojo		
			prefix=prefix.replace("_", "");
			createPojo(table,tableComment,className, cols,prefix);
							
		} 
		log.info("---------创建结束-----------");
		
	}
		
	
	public static void main(String[] args) {
		System.out.println("t_user_acc".substring(0,"t_user_acc".indexOf("_")+1));
	}
	
	/*  
	    * @Description:生成pojo实现方法
	    * 
	    * @param:													是否必须
	    * 
	    * tableName:表名													是
	    * className:生成的类名												是
	    * cols:表所有的列信息													是
	    */
	private  void createPojo(String tableName,String tableComment,String className,List<T2BVO> cols,String prefix) throws Exception {		
		if (!Detect.notEmpty(tableConfig.pojoFilePath())||!Detect.notEmpty(tableConfig.pojoPackagePath())) {
			return;
		}
		String filePath= tableConfig.pojoFilePath().replace(".", "/");
		String packagePath= tableConfig.pojoPackagePath().replace("/", ".");
		if (tableConfig.usePrefixAsDir()) {
			File fileDir = new File(filePath);
			if (!fileDir.exists()) {
				throw new Exception("目录不存在----"+filePath);
			}
			filePath=filePath+(prefix.equals("")?"":"/"+prefix);
			packagePath=packagePath+(prefix.equals("")?"":"."+prefix);
			new File(filePath).mkdirs();
		}
		String classPath =filePath+"/"+ className + ".java";//生成java文件路径
		File classFile = new File(classPath);
		
		if (!classFile.exists()) {
			// 如果不存在，则创建
			try {
				classFile.createNewFile();
				StringBuilder sbImport = new StringBuilder();
				StringBuilder sb = new StringBuilder();
				sbImport.append("package " + packagePath + ";\n\n");
				
				sbImport.append("import "+tableConfig.superPojoPackage()+";\n");
				sbImport.append("import com.fasterxml.jackson.annotation.JsonInclude;\n");
				sb.append("@JsonInclude(JsonInclude.Include.NON_DEFAULT)\n");
				sb.append("public class " + className + " extends "+tableConfig.superPojoName()+"{\n\n");
				//属性			
				sb.append("	public String table=\""+ tableName + "\";//"+tableComment+"\n");
				
				String id="";
				String clowns="\"{";
				String clown1="\" ";
				for (T2BVO vo : cols) {
					String colKey = vo.getColKey();
					String type = vo.getColType().toLowerCase();
					String col = vo.getColName();
					String clown=BeanUtil.columnToField(col);
					clown1+=col+",";
					clowns+="'"+clown+"':'"+col+"',";
					if (colKey.equalsIgnoreCase("PRI")) {
						id=col;
						if (type.contains("bigint")) {
							sb.append("	public Long returnId;//插入数据返回ID\n");
						}else if (type.contains("int")) {
							if (type.contains("unsigned")) {	
								sb.append("	public Long returnId;//插入数据返回ID\n");
							}else {							
								sb.append("	public Integer returnId;//插入数据返回ID\n");
							}
						}
					}
					
				}
				sb.append("	public String primaryKey=\""+ id + "\";//表的主键\n");

				clowns=clowns.substring(0,clowns.length()-1)+"}\"";
				clown1=clown1.substring(0,clown1.length()-1)+" \"";
				sb.append("	public String columns="+ clowns + ";\n");
				sb.append("	//select选择列\n");
				sb.append("	public static String selectColumn1="+ clown1 + ";\n");
				
				String dateImport="";
				String decimalImport="";
				String lengthImport="";
				String notNullImport="";
				String tableCols="";
				boolean hasLong=false;
				for (T2BVO vo : cols) {
					String col = vo.getColName();
					String clown=BeanUtil.columnToField(col);
					String type = vo.getColType().toLowerCase();
					String javaType="";
					tableCols+=","+col;
					if (type.contains("bigint")) {
						hasLong=true;
						sb.append("	@JsonSerialize(using = ToStringSerializer.class)\n");	
						javaType = " Long ";
					}else if (type.contains("int")) {
						if (type.contains("unsigned")) {	
							sb.append("	@JsonSerialize(using = ToStringSerializer.class)\n");							
							javaType = " Long ";
						}else {							
							javaType = " Integer ";
						}
					}else if (type.contains("date")||type.contains("year")||type.contains("time")||type.contains("timestamp")||type.contains("datetime")) {
						javaType = " String ";
						//dateImport="import java.util.Date;\n";
					}else if (type.contains("double")) {
						javaType = " Double ";
					}else if (type.contains("decimal")) {
						javaType = " BigDecimal ";
						decimalImport="import java.math.BigDecimal;\n";
					}else if (type.contains("float")) {
						javaType = " Float ";
					}else {
						javaType = " String ";
						lengthImport="import org.hibernate.validator.constraints.Length;\n";
					}
					sb.append("	private" + javaType + clown + ";");
					sb.append("//" + vo.getColComment() + "\n");
				}
				tableCols=tableCols.replaceFirst(",", "")+";";
				if (hasLong) {
					sbImport.append("import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;\n");
					sbImport.append("import com.fasterxml.jackson.databind.annotation.JsonSerialize;\n");
				}
				sbImport.append(dateImport);
				sbImport.append(decimalImport);
				sbImport.append(lengthImport);
				sbImport.append("\n\n");
				sb.append("\n\n");
				
				sb.append("	//表列名枚举\n");
				sb.append("	public enum "+className+"Col{\n");
				sb.append("		"+tableCols+"\n");
				sb.append("	}\n\n");
				
				// setter & getter
				for (T2BVO vo : cols) {
					String col = vo.getColName();
					String type = vo.getColType().toLowerCase();
					String isNull = vo.getIsNull().toLowerCase();
					String javaType = " String ";
					if (type.contains("bigint")) {
						javaType = " Long ";
					}
					else if (type.contains("int")) {
						if (type.contains("unsigned")) {							
							javaType = " Long ";
						}else {							
							javaType = " Integer ";
						}
					}				 
					else if (type.contains("date")||type.contains("year")||type.contains("time")||type.contains("timestamp")||type.contains("datetime")) {
						javaType = " String ";
					}
					else if (type.contains("double")) {
						javaType = " Double ";
					}else if (type.contains("decimal")) {
						javaType = " BigDecimal ";
					}
					else if (type.contains("float")) {
						javaType = " Float ";
					}
					String property = BeanUtil.columnToField(col);
					if (!id.equals(col)) {
						//非主键加验证注解
						if (isNull.equals("no")) {
							sb.append("	@NotNull(message=\""+property+"不能为空\")\n");
							notNullImport="import javax.validation.constraints.NotNull;\n";
						}
						if (javaType.equals(" String ")&&Detect.notEmpty(vo.getColMaxLength())&&vo.getColMaxLength()!="0") {
							sb.append("	@Length(max="+vo.getColMaxLength()+",message=\""+property+"长度不能超过"+vo.getColMaxLength()+"\")\n");
						}
					}
					
					sb.append("	public" + javaType + "get" + BeanUtil.upperCaseFirst(property) + "(){\n");
					String priCol=BeanUtil.columnToField(id);//主键属性
					if (property.equals(priCol)) {
						sb.append("		if ("+priCol+"!=null) {\n");
						sb.append("			return "+priCol+";\n");
						sb.append("		}else {\n");
						sb.append("			return returnId;\n");
						sb.append("		}\n");
					}else {
						sb.append("		return " + property + ";\n");
					}
					sb.append("	}\n");

					sb.append("	public void set" + BeanUtil.upperCaseFirst(property) + "(" + javaType.trim() + " "
							+ property + "){\n");
					sb.append("		this." + property + " = " + property + ";\n");
					sb.append("	}\n\n");
				}
				
				//toString					
				/*sb.append("	@Override\n");
				sb.append("	public String toString(){\n");
				sb.append("		return \""+className +"[pageNum=\"+pageNum+\",pageSize=\"+pageSize+\",order=\"+order+\",sort=\"+sort+\n");
				sb.append("		\",");
				int i=1;
				for (T2BVO vo : cols) {
					String col = vo.getColName();
					String clown=BeanUtil.columnToField(col);				
					sb.append( clown+"=\"+"+clown+"+\""+(i!=cols.size()?",":""));
					if (i%5==0) {
						sb.append("\"\n");
						sb.append("		+\"");
					}
					i++;
				}
				sb.append("]\";\n");
				sb.append("	}\n\n");*/
						
				
				sbImport.append(notNullImport);
				sb.append("\n\n}\n\n");
				sbImport.append(sb);
				OutputStream os = new FileOutputStream(classFile);
				PrintStream ps = new PrintStream(os);
				ps.print(sbImport);

				os.flush();
				os.close();
				ps.flush();
				ps.close();

			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
